#ifndef __MVT_SXML_H__
#define __MVT_SXML_H__

#include "mvdef.h"

MVCXX_EXTERN_BEGIN

/*********************************************************
 *
 *                   SXML 解析API
 *
 ********************************************************/
///< TODO: 待补充实现

/*********************************************************
 *
 *        MXML 宏形式封装API，更灵活和节省资源；
 *            但是宏展开后的代码量会相对偏多
 *    封装目的是能以更接近目标xml结构的直观形式编写代码
 *
 ********************************************************/
#if 0
#include "mvdef.h"
#include "mvos/mvos_apis.h"
#include "mvt_utilities/mvt_sxml.h"
/** 典型调用示例，输出结果：<CompleteMultipartUpload><Part><PartNumber>1</PartNumber><ETag>"a54357aff0632cce46d942af68356b38"</ETag></Part><Part><PartNumber>2</PartNumber><ETag>"0c78aef83f66abc1fa1e8477f296d394"</ETag></Part><Part><PartNumber>3</PartNumber><ETag>"acbd18db4cc2f85cedef654fccc4a4d8"</ETag></Part></CompleteMultipartUpload> */
mv_s32_t main(mv_void_t)
{
    mv_v8ptr_t _pv8_out = NULL;
    mv_v8_t    _av8_stack_cache[512];
    mv_s32_t   _s32_outlen = 0;

    _pv8_out = _av8_stack_cache;

    mvt_mxml_build(_pv8_out, 512, _s32_outlen,
        mvt_mxml_obj("CompleteMultipartUpload",
            mvt_mxml_obj("Part",
                mvt_mxml_num("PartNumber", 1);
                mvt_mxml_str("ETag",       "a54357aff0632cce46d942af68356b38");
            );
            mvt_mxml_obj("Part",
                mvt_mxml_num("PartNumber", 2);
                mvt_mxml_str("ETag",       "0c78aef83f66abc1fa1e8477f296d394");
            );
            mvt_mxml_obj("Part",
                mvt_mxml_num("PartNumber", 3);
                mvt_mxml_str("ETag",       "acbd18db4cc2f85cedef654fccc4a4d8");
            );
        );
    );
    if (_s32_outlen < 0) {
        mvos_dbg_printf("mxml build failed: %d\n", _s32_outlen);
    } else if (_pv8_out) {
        mvos_dbg_printf("output======>\n%s\n========= len: %d\n", _pv8_out, _s32_outlen);
    }
    if (_pv8_out != _av8_stack_cache) {
        mvos_free(_pv8_out);
    }
    return 0;
}
#endif
/**
 * @brief 开始一个新的XML构建
 * 
 * @param pout      [out] json输出缓存地址(这个参数需要是指针，不能直接用数组)
 * @param max        [in] 输出缓冲大小
 * @param out_len    [in] 实际输出json长度
 * @param ...        [in] json操作嵌套代码
 * @return 构建结果，根据out_len判断
 * - success : out_len > 0
 * -  failed : MV_EC_RESOURCE_LEAK (缓存大小不足)
 *             MV_EC_OUT_OF_RANGE  (XML格式非法)
 * @note 当pout输入的变量指向NULL，会自动按照max申请内存，需要用户自行判断释放
 * @note 下面所有mxml的嵌套代码封装，均需要在build范围内调用，自动关联处理
 */
#define mvt_mxml_build(pout, max, out_len, ...)    \
do {                                                       \
    mv_v8ptr_t _tmp_pv8_mxml_build = NULL;                 \
    mv_s32_t   _tmp_s32_mxml_size  = max;                  \
    mv_s32_t   _tmp_s32_result      = 0;                   \
    mv_s32_t   _tmp_s32_off         = 0;                   \
    mv_v8_t    _tmp_av8_num_str[64] = {0};                 \
    if (pout) {                                            \
        _tmp_pv8_mxml_build = pout;                        \
    }  else {                                              \
        pout = _tmp_pv8_mxml_build = mvos_zalloc(max);     \
    }                                                      \
    do{__VA_ARGS__;}while(0);                              \
    if (_tmp_s32_result < 0) {                             \
        out_len = _tmp_s32_result;                         \
    } else {                                               \
        out_len = _tmp_s32_off;                            \
        if ((_tmp_s32_off > 0)                             \
        && (_tmp_pv8_mxml_build[_tmp_s32_off-1] == ',')) { \
            _tmp_pv8_mxml_build[_tmp_s32_off-1] = '\0';    \
            _tmp_s32_off--;                                \
            out_len--;                                     \
        }                                                  \
    }                                                      \
} while (0);
/**
 * @brief (XML操作嵌套代码封装:)XML对象
 * 
 * @param key        [in] 对象key名称
 * @param ...        [in] xml操作嵌套代码
 *
 * @note 需要在build范围内使用，自动关联处理
 */
#define mvt_mxml_obj(key, ...)                                                                                         \
_tmp_s32_result = mvos_snprintf(_tmp_pv8_mxml_build+_tmp_s32_off, (_tmp_s32_mxml_size-_tmp_s32_off), "<%s>", key);     \
if (_tmp_s32_result <= 0) {break;} _tmp_s32_off += _tmp_s32_result;                                                    \
__VA_ARGS__;                                                                                                           \
_tmp_s32_result = mvos_snprintf(_tmp_pv8_mxml_build+_tmp_s32_off, (_tmp_s32_mxml_size-_tmp_s32_off), "</%s>", key);    \
if (_tmp_s32_result <= 0) {break;} _tmp_s32_off += _tmp_s32_result;
/**
 * @brief (XML操作嵌套代码封装:)XML整数
 * 
 * @param key        [in] 对象key名称
 * @param num        [in] 整数数值
 *
 * @note 需要在build范围内使用，自动关联处理
 */
#define mvt_mxml_num(key, num)                                                                                                                     \
mvos_integer2str_scal((num),_tmp_av8_num_str,sizeof(_tmp_av8_num_str),10,MVOS_INT2STR_STYLE_NONE,0);                                               \
_tmp_s32_result = mvos_snprintf(_tmp_pv8_mxml_build+_tmp_s32_off, (_tmp_s32_mxml_size-_tmp_s32_off), "<%s>%s</%s>", key, _tmp_av8_num_str, key);  \
if (_tmp_s32_result <= 0) {break;} _tmp_s32_off += _tmp_s32_result;
/**
 * @brief (XML操作嵌套代码封装:)XML字符串
 * 
 * @param key        [in] 对象key名称
 * @param str        [in] 字符串内容起始地址
 *
 * @note 需要在build范围内使用，自动关联处理
 */
#define mvt_mxml_str(key, str)                                                                                                        \
_tmp_s32_result = mvos_snprintf(_tmp_pv8_mxml_build+_tmp_s32_off, (_tmp_s32_mxml_size-_tmp_s32_off), "<%s>%s</%s>", key, str, key);  \
if (_tmp_s32_result <= 0) {break;} _tmp_s32_off += _tmp_s32_result;

MVCXX_EXTERN_END

#endif
